home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 008 / bonus.arc / ADIM.LSP < prev    next >
Encoding:
Text File  |  1986-07-04  |  14.1 KB  |  328 lines

  1.  
  2. ;                          Associative Dimensioning
  3.  
  4. ;                            by Kelvin R. Throop
  5. ;                        Revision 3  --  May 18, 1986
  6.  
  7. ;   BACKGROUND
  8.  
  9. ;   Dimensions  which change automatically when the associated geometry is
  10. ;   modified are a very useful feature and oft requested by AutoCAD users.
  11. ;   Autodesk  will  probably  provide  this capability in a future AutoCAD
  12. ;   release, but until then a workable  facility  can  be  implemented  in
  13. ;   AutoLISP.
  14.  
  15. ;   There  are  two  ways  to  provide this capability.  To avoid semantic
  16. ;   tangles, I will designate them "attached dimensions" and  "stretchable
  17. ;   dimensions".  Both are ways of achieving what I will term "associative
  18. ;   dimensioning".
  19.  
  20. ;   An attached dimension is an entity which is linked in the database  to
  21. ;   the  point on the geometry which it specifies.  This implies a pointer
  22. ;   (associativity, in the IGES sense) from the dimension to the  geometry
  23. ;   and  probably  a  backpointer from the geometry to the dimension.  The
  24. ;   dimension may have other non-geometric properties, such as text style,
  25. ;   dimension  line  location,  arrow  style, etc., but its measurement is
  26. ;   derived directly from the database.
  27.  
  28. ;   When any editing operation modifies the point in the database to which
  29. ;   the dimension points, the dimension is recalculated and updated on the
  30. ;   screen.  Because the dimension is  specified  as  a  relation  between
  31. ;   database  points,  any  editing  operation which modifies a point will
  32. ;   automatically update the dimension.
  33.  
  34. ;   Attached dimensions  are  the  obvious  way  of  allowing  editing  to
  35. ;   automatically update dimensions.  The implementation problems, and the
  36. ;   problems in explaining  such  a  system  to  the  user,  however,  are
  37. ;   daunting.   For  example,  suppose  the  user draws a box and places a
  38. ;   horizontal dimension  along  the  top.   Next,  the  user  draws  both
  39. ;   diagonals  of  the  box,  and  attaches  another  box  to  the  right.
  40.  
  41. ;   The right end of the dimension now points to the intersection of three
  42. ;   lines.  Suppose only one is moved.  Does the dimension move?  Does the
  43. ;   dimension attach to only the original top of the  box?   Why  not  the
  44. ;   right  side  also?   You  see  the  problem:  there  is  no  graphical
  45. ;   indication of which the dimension attaches, and it's  far  from  clear
  46. ;   that  a drafter is likely to think in terms of pointers and attachment
  47. ;   lists: he KNOWS what  the  bloody  dimension  points  to,  thank  you!
  48.  
  49. ;   Stretchable  dimensions  are drawing entities with a set of key points
  50. ;   which specify their value.  Drawing a  stretchable  dimension  inserts
  51. ;   one  of  these  entities,  and  draws  a  dimension value based on the
  52. ;   definition points.  (We will henceforth consider linear dimensions  as
  53. ;   an  example;  the  extrapolation  to  other  dimension types should be
  54. ;   self-evident).   In  a  linear  dimension,  the  two  extension   line
  55. ;   attachment  points  specify  the  distance  to  be  dimensioned.   The
  56. ;   dimension is assumed to be one entity, so it may be  moved  bodily  by
  57. ;   any  of  the  editing  commands,  but  its  internal structure is left
  58. ;   unchanged by them.  The STRETCH command, however, allows one  to  grow
  59. ;   or  shrink the dimension if only one of its endpoints is caught in the
  60. ;   window being  stretched.   When  such  a  STRETCH  is  performed,  the
  61. ;   dimension is remeasured and updated on the screen to represent the new
  62. ;   measurement.
  63.  
  64. ;   Note that stretchable linear dimensions are really just very  overdone
  65. ;   line  entities:  when  you  change their endpoints, you just get a lot
  66. ;   more action than for a mundane old line entity.
  67.  
  68. ;   USER NOTES
  69.  
  70. ;   Stretchable dimensions can be added to  AutoCAD  via  AutoLISP.   They
  71. ;   aren't  even  particularly  difficult to implement.  This Lisp program
  72. ;   and  associated  menu  and  drawing  demonstrate  stretchable   linear
  73. ;   dimensions.   This is in no way a finished product.  It is intended to
  74. ;   illustrate what can be done with AutoLISP and to serve  as  a  jumping
  75. ;   off  point  for  developers  who  wish to add such facilities to their
  76. ;   packages.
  77.  
  78. ;   Be sure you download all of the related files:
  79.  
  80. ;           ADIM.MNU             - Control menu
  81. ;           ADIMBLK.DWG          - Data block definition
  82. ;           ADIM.LSP             - Lisp implementation
  83.  
  84. ;   To exercise the facility, load the files  into  your  current  working
  85. ;   drawing  directory.   Bring up AutoCAD on a new drawing, and enter the
  86. ;   command:
  87.  
  88. ;       MENU ADIM
  89.  
  90. ;   This will load the associative dimensioning menu.  Pick the LOAD  item
  91. ;   on  the  menu,  and  the  Lisp  portion of the package will be loaded.
  92.  
  93. ;   To insert an associative linear dimension, pick DIM on  the  menu  (or
  94. ;   enter the command ADIM).  You will be asked:
  95.  
  96. ;       Dimension type (horiz/vertical/aligned):
  97.  
  98. ;   Enter  the desired type (no abbreviations, please).  Then reply to the
  99. ;   prompts:
  100.  
  101. ;       First extension line location:
  102. ;       Second extension line location:
  103. ;       Dimension line location:
  104.  
  105. ;   with  points  specifying  the  dimension.   Any  of  the  dimensioning
  106. ;   variables   may   be   preset  with  the  drawing  modes  you  prefer.
  107.  
  108. ;   The dimension will be drawn on the screen.  Go ahead and draw  several
  109. ;   dimensions,   attaching   them   to   whatever   geometry   you  like.
  110.  
  111. ;   To stretch dimensions, pick STRETCH on the menu.  Follow  the  prompts
  112. ;   for the command (which will be defaulted to a single pick by CROSSES),
  113. ;   and window dimension endpoints.  After the geometry  is  updated,  all
  114. ;   the dimensions will be changed automatically.
  115.  
  116. ;   If  you prefer to "roll your own" STRETCH command, just type DIMUPD to
  117. ;   update  the  dimensions   after   the   STRETCH   command   completes.
  118.  
  119. ;   HOW DOES IT WORK?
  120.  
  121. ;   When  a dimension is acquired by the DIM menu pick (ADIM command), the
  122. ;   C:ADIM Lisp function obtains the  arguments,  then  calls  DRAWDIM  to
  123. ;   construct  the  dimension.  DRAWDIM inserts two instances of the block
  124. ;   ADIMBLK before the dimension.  This block is inserted at either end of
  125. ;   the  dimensioned  distance,  with  attributes  which record all of the
  126. ;   user-supplied information to the command.  Then AutoCAD is allowed  to
  127. ;   draw  the  dimension  using the DIM1 command.  The entities which went
  128. ;   into the dimension are then collected into a  block  (given  a  unique
  129. ;   name  from  the  current  time),  and  inserted  at -3000,-3000 so the
  130. ;   insertion point of the block will not be caught in a  STRETCH  window.
  131.  
  132. ;   After  a  STRETCH,  C:DIMUPD  is called.  It obtains the selection set
  133. ;   used by the STRETCH by (ssget "p") and scans  it.   If  ADIMBLKs  were
  134. ;   caught in the selection set, endpoints of dimensions were changed.  If
  135. ;   this has happened, DIMUPD steps  forward  and  deletes  the  dimension
  136. ;   block, then calls DRAWDIM to update the dimension.
  137.  
  138. ;   PROBLEMS
  139.  
  140. ;   Deleting  the  old  dimension  block  reference doesn't get rid of the
  141. ;   block definition, and there's no command to do this.  The user  should
  142. ;   periodically  PURGE block definitions if a lot of dimensions are being
  143. ;   changed.
  144.  
  145. ;   Moving both endpoints of a dimension messes it up.  I was lazy and did
  146. ;   not  scan  the  selection  set  for the special case of both endpoints
  147. ;   being moved.  This code was a proof of concept, and  I  chose  not  to
  148. ;   make it exhaustive.  The fix is obvious.
  149.  
  150. ;   When  you move the second point of a dimension, a redundant ADIMBLK P1
  151. ;   remains in the database.  AutoLISP should have an  (ENTPREV)  function
  152. ;   to  get the preceding entity.  Lacking one, when the second definition
  153. ;   point is picked I have the choice of leaving the first in the database
  154. ;   or  scanning  the  entire  database to find and delete it.  I chose to
  155. ;   leave it there, since any subsequent  change  which  catches  it  will
  156. ;   delete it.
  157.  
  158. ;   WHY IS IT SO SLOW?
  159.  
  160. ;   You  might  be  surprised.   As  far as I can tell, DRAWDIM and DIUMPD
  161. ;   spend most of their time converting floating point numbers to and from
  162. ;   ASCII.  Since the only way I can save points in attributes is to store
  163. ;   two attributes as 12 digit precision scientific notation reals, I have
  164. ;   to go through a lot of editing and scanning, and it takes a long time.
  165.  
  166. (defun C:ADIM (/ p1 p2 p3 s bm ce)
  167.  
  168. ;       Obtain dimension type string
  169.  
  170.         (setq s "")
  171.         (while (= (strlen s) 0)
  172.            (setq s (getstring "\nDimension type (horiz/vertical/aligned): "))
  173.            (setq s (strcase s))
  174.            (if (not (or (= s "HORIZ") (= s "VERTICAL") (= s "ALIGNED")))
  175.               (setq s "")
  176.            )
  177.         )
  178.  
  179. ;       Get dimension definition points
  180.  
  181.         (setq p1 (getpoint "\nFirst extension line location: "))
  182.         (setq p2 (getpoint "\nSecond extension line location: " p1))
  183.  
  184. ;       Obtain extension line location
  185.  
  186.         (setq p3 (getpoint "\nDimension line location: "))
  187.  
  188.         (setq bm (getvar "blipmode"))
  189.         (setq ce (getvar "cmdecho"))
  190.         (setvar "blipmode" 0)
  191.         (setvar "cmdecho" 0)
  192.  
  193.         (drawdim s p1 p2 p3)
  194.  
  195.         (setvar "blipmode" bm)
  196.         (setvar "cmdecho" ce)
  197. )
  198.  
  199. ;       Draw dimension and insert attribute blocks
  200.  
  201. (defun drawdim (s p1 p2 p3 / e1 s1 bn)
  202.  
  203. ;       Insert attribute blocks at both dimensioned points
  204.  
  205.         (command "insert" "adimblk" p1 1 1 0)
  206.         (command "P1")                       ; Dimval
  207.         (command (rtos (car p1) 1 12))       ; p1x
  208.         (command (rtos (cadr p1) 1 12))      ; p1y
  209.         (command (rtos (car p2) 1 12))       ; p2x
  210.         (command (rtos (cadr p2) 1 12))      ; p2y
  211.         (command (rtos (car p3) 1 12))       ; p3x
  212.         (command (rtos (cadr p3) 1 12))      ; p3y
  213.         (command s)                          ; type
  214.  
  215.         (command "insert" "adimblk" p2 1 1 0)
  216.         (command "P2")                       ; Dimval
  217.         (command (rtos (car p1) 1 12))       ; p1x
  218.         (command (rtos (cadr p1) 1 12))      ; p1y
  219.         (command (rtos (car p2) 1 12))       ; p2x
  220.         (command (rtos (cadr p2) 1 12))      ; p2y
  221.         (command (rtos (car p3) 1 12))       ; p3x
  222.         (command (rtos (cadr p3) 1 12))      ; p3y
  223.         (command s)                          ; type
  224.  
  225. ;       Draw the dimension
  226.  
  227.         (setq e1 (entlast))        ; Remember last entity in database
  228.         (command "dim1" s p1 p2 p3 "")
  229.  
  230. ;       Now suck up the entities generated by dimensioning and make
  231. ;       a block of them.
  232.  
  233.         (setq s1 (ssadd))          ; Create selection set of entities
  234.         (while (setq e1 (entnext e1))
  235.            (ssadd e1 s1)
  236.         )
  237.         ; Make unique name for block from current date and time
  238.         (setq s (rtos (getvar "date") 2 9))
  239.         (setq bn (strcat "$DIM" (substr s 1 7) (substr s 9)))
  240.         (command "block" bn '(-3000 -3000) s1 "")
  241.         (command "insert" bn '(-3000 -3000) 1 1 0)
  242. )
  243.  
  244. ;       Postprocessing for stretch command which updates dimensions
  245.  
  246. (defun C:DIMUPD (/ s1 bm ce hen)
  247.  
  248.         (setq bm (getvar "blipmode"))
  249.         (setq ce (getvar "cmdecho"))
  250.         (setvar "blipmode" 0)
  251.         (setvar "cmdecho" 0)
  252.  
  253.         (setq s1 (ssget "p"))      ; Obtain last selection set
  254.         (setq i 0)
  255.         (while (setq en (ssname s1 i))
  256.            (setq e (entget en))
  257.            (if (and (= (cdr (assoc 0 e)) "INSERT")
  258.                     (= (cdr (assoc 2 e)) "ADIMBLK")
  259.                )
  260.               (progn
  261.                  (setq hen en)
  262.                  (setq ndp (cdr (assoc 10 e)))  ; New dimensioned point
  263.                  (setq al (basl))
  264.                  (entdel hen)      ; Delete dimension record info
  265.                  (setq ok t)
  266.                  (if (= (setq dv (cdr (assoc "DIMVAL" al))) "P1")
  267.                     (progn
  268.                        ; See if this P1 is followed by a P2.  If so,
  269.                        ; delete it also.
  270.                        (setq e (entget (setq en (entnext en))))
  271.                        (if (and (= (cdr (assoc 0 e)) "INSERT")
  272.                                 (= (cdr (assoc 2 e)) "ADIMBLK")
  273.                            )
  274.                           (progn
  275.                              (setq hen en)
  276.                              (setq al1 (basl))
  277.                              (if (not (= (cdr (assoc "DIMVAL" al1)) "P2"))
  278.                                 (setq ok nil)     ; Nope.  Don't blunder on
  279.                                 (entdel hen)      ; Valid.  Delete old P2
  280.                              )
  281.                           )
  282.                           (setq ok nil)
  283.                        )
  284.                     )
  285.                  )
  286.                  (setq e (entget (setq en (entnext en))))
  287.                  (if (and ok (= (cdr (assoc 0 e)) "INSERT")
  288.                              (= (substr (cdr (assoc 2 e)) 1 4) "$DIM"))
  289.                     (progn
  290.                        (entdel en)
  291.                        (setq p1 (list (cdr (assoc "DIMP1X" al))
  292.                                       (cdr (assoc "DIMP1Y" al))))
  293.                        (setq p2 (list (cdr (assoc "DIMP2X" al))
  294.                                       (cdr (assoc "DIMP2Y" al))))
  295.                        (setq p3 (list (cdr (assoc "DIMP3X" al))
  296.                                       (cdr (assoc "DIMP3Y" al))))
  297.                        (if (= dv "P1")
  298.                           (setq p1 ndp)
  299.                           (setq p2 ndp)
  300.                        )
  301.                        (drawdim (cdr (assoc "DIMTYPE" al)) p1 p2 p3)
  302.                     )
  303.                  )
  304.               )
  305.            )
  306.            (setq i (1+ i))
  307.         )
  308.  
  309.         (setvar "blipmode" bm)
  310.         (setvar "cmdecho" ce)
  311. )
  312.  
  313. ;       Build association list from attributes
  314.  
  315. (defun basl (/ v e t o)
  316.         (setq v nil)
  317.         (while (not (= (cdr (assoc 0 (setq e (entget (setq en (entnext en))))))
  318.                      "SEQEND"))
  319.            (setq t (cdr (assoc 2 e)))
  320.            (setq o (cdr (assoc 1 e)))
  321.            (if (= (substr t 1 4) "DIMP")
  322.               (setq o (atof o))
  323.            )
  324.            (setq v (cons (cons t o) v))
  325.         )
  326.         v
  327. )
  328.